﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;

namespace Golden_Miner
{
    /// <summary>
    /// 游戏类
    /// </summary>
    class Game
    {
        //游戏区域大小
        public const int GameWidth = 975;
        public const int GameHeight = 708;

        //矿石列表
        private List<Ore> goldOres { get; set; }
        private List<Ore> stoneOres { get; set; }
        private List<Ore> walletOres { get; set; }

        //定义数值：目标、当前金钱，倒计时，第几关
        private int Goal = 650;
        private int GetMoney = 0;
        private int Round = 1;
        private int ShowTime = 60;
        private int countDown = 0;
        private int wholeRound = 2;
        private bool islose = false;
        private bool iswin = false;

        //定义其他类
        private Hook _hook;
        private Ore _ore;
        private Man _man;
        private Lose _lose;
        private Win _win;

        //过程中使用到的随机数
        private static Random rd = new Random();

        //定义人的动态
        private bool isMoveman;

        //设置时间
        private System.Timers.Timer timer { get; set; }
        //定义委托
        public delegate void GameEvent();
        //定义事件
        public event GameEvent gameChanged;
        public event GameEvent gameLose;
        public event GameEvent gameWin;

        public Game()
        {
            _hook = new Hook(new Rectangle());
            _ore = new Ore(new Rectangle());
            _man = new Man(new Rectangle((GameWidth - 190) / 2, 15, 181, 102));
            _lose = new Lose(new Rectangle(0, 0, GameWidth, GameHeight));
            _win = new Win(new Rectangle(0, 0, GameWidth, GameHeight));

            isMoveman = false;
            stoneOres = new List<Ore>();
            goldOres = new List<Ore>();
            walletOres = new List<Ore>();
            chooseRound(Round);



            //时间控制
            timer = new System.Timers.Timer();
            timer.Elapsed += Timer_Elapsed;
            timer.Start();
        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //时钟处理程序
            CountDown();

            //钩子移动
            _hook.Tick();

            //处理碰撞
            HandleTouch();

            //小人移动
            _man.moveMan(isMoveman, ShowTime);

            //判断输赢
            if (ShowTime == 0)
            {
                if (GetMoney >= Goal && Round <wholeRound )
                {
                    Goal += 650;
                    Round++;
                    ShowTime = 60;
                    stoneOres.Clear();
                    goldOres.Clear();
                    walletOres.Clear();
                    _hook.length = 10;
                    chooseRound(Round);                    
                }
                else if(GetMoney >=Goal && Round==wholeRound )
                {
                    iswin = true;
                    timer.Stop();
                    gameWin();
                }
                else
                {
                    islose = true;
                    timer.Stop();
                    gameLose();
                }
            }
            else
            {
                gameChanged();
            }
        }

        /// <summary>
        /// 处理碰撞
        /// </summary>
        private void HandleTouch()
        {
            int stoneidx = -1;
            foreach (var ore in stoneOres.ToArray ())
            {
                if (ore.Rectangle.Contains(_hook.rePoint(_hook.length, _hook.angle)))
                {
                    stoneidx = stoneOres.IndexOf(ore);
                    break;
                }
            }
            if (stoneidx != -1)
            {
                //让小人动起来
                isMoveman = true;

                //获取矿石大小从而确定回收的速度
                int oresize = _ore.oreSize(stoneOres[stoneidx].Rectangle.Height);
                _hook.hookBack(oresize);

                //到顶之后矿石消失，增加金钱
                do
                {
                    Point tempPoint = new Point(0, 0);
                    if (stoneOres[stoneidx].Rectangle.X > 465)
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    else
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X - 30 * oresize, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    stoneOres[stoneidx] = new Ore(new Rectangle(tempPoint, _ore.OreSize(oresize)));
                } while (_hook.length > 10);
                stoneOres.Remove(stoneOres[stoneidx]);
                isMoveman = false;
                GetMoney += (10 * oresize);                        
            }

            int goldidx = -1;
            foreach (var ore in goldOres.ToArray())
            {
                if (ore.Rectangle.Contains(_hook.rePoint(_hook.length, _hook.angle)))
                {
                    goldidx = goldOres.IndexOf(ore);
                    break;
                }
            }
            if (goldidx != -1)
            {
                //让小人动起来
                isMoveman = true;

                //获取矿石大小从而确定钩子收回的速度
                int oresize = _ore.oreSize(goldOres[goldidx].Rectangle.Height);
                _hook.hookBack(oresize);

                //到顶之后矿石消失，增加金钱
                do
                {
                    Point tempPoint = new Point(0, 0);
                    if (goldOres [goldidx].Rectangle .X>465)
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    else
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X-30* oresize, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    goldOres [goldidx] = new Ore(new Rectangle(tempPoint, _ore.OreSize(oresize)));
                } while (_hook.length > 10);
                goldOres.Remove(goldOres[goldidx]);
                isMoveman = false ;
                GetMoney += 50*oresize*oresize;
            }
            int walletidx = -1;
            foreach (var ore in walletOres.ToArray())
            {
                if (ore.Rectangle.Contains(_hook.rePoint(_hook.length, _hook.angle)))
                {
                    walletidx = walletOres.IndexOf(ore);
                    break;
                }
            }
            if (walletidx != -1)
            {
                //让小人动起来
                isMoveman = true;

                // 获取矿石大小从而确定钩子收回的速度
                int oresize = _ore.oreSize(walletOres[walletidx].Rectangle.Height);
                _hook.hookBack(oresize);

                //到顶之后矿石消失，增加金钱
                do
                {
                    Point tempPoint = new Point(0, 0);
                    if (walletOres[walletidx].Rectangle.X > 465)
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    else
                    {
                        tempPoint = new Point(_hook.rePoint(_hook.length, _hook.angle).X - 30 * oresize, _hook.rePoint(_hook.length, _hook.angle).Y);
                    }
                    walletOres[walletidx] = new Ore(new Rectangle(tempPoint, _ore.OreSize(oresize)));
                } while (_hook.length > 10);
                walletOres.Remove(walletOres[walletidx]);
                isMoveman = false;
                int walletValue = rd.Next(100, 800);
                GetMoney += walletValue;               

            }

        }

        /// <summary>
        /// 绘图游戏场景
        /// </summary>
        /// <param name="g"></param>
        /// <param name="size"></param>
        public void Draw(Graphics g, Size size)
        {
            //定义空白的图
            Image img = new Bitmap(GameWidth, GameHeight);
            Graphics _g = Graphics.FromImage(img);

            ///定义一个矩形，长宽是预定义
            Rectangle rec = new Rectangle(new Point(0, 0), new Size(GameWidth, GameHeight));

            //画开局背景
            _g.DrawImage(Properties.Resources.游戏背景, rec);

            //失败界面
            if (islose)
            {
                _lose.Draw(_g);
            }
            else if(iswin)
            {
                _win.Draw(_g);
            }
            else
            {
                //画人
                _man.Draw(_g);

                //画数值
                _g.DrawString(ShowTime.ToString(), new Font("宋体", 25), new SolidBrush(Color.Red), new Point(910, 15));
                _g.DrawString(Goal.ToString(), new Font("宋体", 25), new SolidBrush(Color.Red), new Point(150, 60));
                _g.DrawString(GetMoney.ToString(), new Font("宋体", 25), new SolidBrush(Color.Red), new Point(80, 15));
                _g.DrawString(Round.ToString(), new Font("宋体", 25), new SolidBrush(Color.Red), new Point(880, 55));

                //画矿石
                foreach (var ore in stoneOres.ToArray())
                {
                    ore.stoneDraw(_g);
                }
                foreach (var ore in goldOres.ToArray())
                {
                    ore.goldDraw(_g);
                }
                foreach (var ore in walletOres.ToArray())
                {
                    ore.walletDraw(_g);
                }
                //画钩子
                _hook.Draw(_g);
            }

            //todo
            g.DrawImage(img, new Rectangle(new Point(0, 0), size));
        }

        /// <summary>
        /// 倒计时
        /// </summary>
        private void CountDown()
        {
            countDown++;
            if (ShowTime <= 60 && ShowTime > 0 && countDown % 10 == 0)
            {
                ShowTime--;
            }
        }

        /// <summary>
        /// 不同关卡的矿石位置
        /// </summary>
        /// <param name="nowRound">关卡</param>
        private void chooseRound(int nowRound)
        {
            switch (nowRound)
            {
                case 1:
                    foreach (var stonePoint in _ore._stonePoints1)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(stonePoint, _ore.OreSize(oresize)));
                        stoneOres.Add(ore);
                        //Value.Add(oresize);
                    }
                    foreach (var goldPoint in _ore._goldPoints1)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(goldPoint, _ore.OreSize(oresize)));
                        goldOres.Add(ore);
                        //Value.Add(oresize);
                    }
                    foreach (var walletPoint in _ore._walletPoints1)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(walletPoint, _ore.OreSize(oresize)));
                        walletOres.Add(ore);
                        //Value.Add(oresize);
                    }
                    break;
                case 2:
                    foreach (var stonePoint in _ore._stonePoints2)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(stonePoint, _ore.OreSize(oresize)));
                        stoneOres.Add(ore);
                    }
                    foreach (var goldPoint in _ore._goldPoints2)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(goldPoint, _ore.OreSize(oresize)));
                        goldOres.Add(ore);
                    }
                    foreach (var walletPoint in _ore._walletPoints2)
                    {
                        //生成一个随机数，决定矿石大小
                        int oresize = rd.Next(1, 4);
                        Ore ore = new Ore(new Rectangle(walletPoint, _ore.OreSize(oresize)));
                        walletOres.Add(ore);
                    }
                    break;
            }
        }

        /// <summary>
        /// 获取键盘
        /// </summary>
        /// <param name="key"></param>
        public void KeyDown(Keys key)
        {
            _hook.KeyDown(key);
        }

    }
}
